/*
 * Copyright (C) 2010 M. Hautle.
 * 
 * This file is part of TrackedBean.
 * 
 * TrackedBean is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option) any later version.
 * 
 * TrackedBean is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License along with TrackedBean. If not, see <http://www.gnu.org/licenses/>.
 */
package ch.trackedbean.internal.weaving;

import java.util.*;
import java.util.concurrent.*;
import org.eclipse.osgi.baseadaptor.bundlefile.*;
import org.eclipse.osgi.baseadaptor.loader.*;
import org.osgi.framework.*;
import org.osgi.util.tracker.*;

/**
 * The class loading hook of TrackedBean.<br>
 * It delegates then the work to the responsible {@link ITrackedBeanWeavingService}.
 * 
 * @author M. Hautle
 */
class TrackedBeanClassLoadingHook extends AbstractTrackedBeanClassLoadingHook {
    /** The weaving services, using {@link ITrackedBeanWeavingService#getAssociatedBundle()} as key. */
    private Map<String, ITrackedBeanWeavingService> services = new ConcurrentHashMap<String, ITrackedBeanWeavingService>();

    /** The service tracker for {@link ITrackedBeanWeavingService}s. */
    private ServiceTracker serviceTracker;

    /** The bundle context. */
    private BundleContext ctx;

    /**
     * {@inheritDoc}
     */
    @Override
    public byte[] processClass(String name, byte[] classbytes, ClasspathEntry classpathEntry, BundleEntry entry, ClasspathManager manager) {
        final ITrackedBeanWeavingService s = services.get(classpathEntry.getBaseData().getSymbolicName());
        return s != null ? s.processClass(name, classbytes, manager) : null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void frameworkStart(BundleContext context) throws BundleException {
        ctx = context;
        serviceTracker = new ServiceTracker(context, ITrackedBeanWeavingService.class.getName(), this);
        serviceTracker.open();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void frameworkStopping(BundleContext context) {
        serviceTracker.close();
        serviceTracker = null;
        services.clear();
        ctx = null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Object addingService(ServiceReference reference) {
        final ITrackedBeanWeavingService s = (ITrackedBeanWeavingService) ctx.getService(reference);
        services.put(s.getAssociatedBundle(), s);
        return s;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void removedService(ServiceReference reference, Object service) {
        final ITrackedBeanWeavingService s = (ITrackedBeanWeavingService) service;
        services.remove(s.getAssociatedBundle());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void modifiedService(ServiceReference reference, Object service) {
        removedService(reference, service);
    }
}
